Registers are value containers which reside on the CPU and not in RAM. They are small in size and some have special purposes. You may store both addresses and values in registers and depending on the instruction used the data inside will be interpreted in a different way - this is commonly called an addressing mode.
In x86 Intel assembly (i386), the registers are 32 bits (4 bytes) in size and some of them are reserved:
ebp
- the base pointer, points to the bottom of the current stack frame
esp
- the stack pointer, points to the top of the current stack frame
eip
- the instruction pointer, points to the next instruction to be executed
The other registers are general purpose registers and can be used for anything you like:
eax
, ebx
, ecx
, edx
, esi
, edi
.
x64 AMD assembly (amd64) extends these 32-bit registers to 64-bit ones and denotes these new versions by replacing the initial e
with an r
: rbp
, rsp
, rip
, rax
, ... It is important to note that these are not different registers - eax
and rax
refer to the same space on the CPU, however, eax
only provides access to the lower 32 bits of the 64-bit register. You can also get access to the lower 16 and 8 bits of the register using different names:
8 Byte Register | Lower 4 Bytes | Lower 2 Bytes | Lower Byte |
---|---|---|---|
rbp | ebp | bp | bpl |
rsp | esp | sp | spl |
rip | eip | ||
rax | eax | ax | al |
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | esi | si | sil |
rdi | edi | di | dil |
r8 | r8d | r8w | r8b |
r9 | r9d | r9w | r9b |
r10 | r10d | r10w | r10b |
r11 | r11d | r11w | r11b |
r12 | r12d | r12w | r12b |
r13 | r13d | r13w | r13b |
r14 | r14d | r14w | r14b |
r15 | r15d | r15w | r15b |
Each row contains names which refer to different parts of the same register. Note, you cannot access the lower 16 or 8 bits of the instruction pointer.
You might sometimes see WORD
or DWORD
being used in a similar context - WORD
means 4 bytes and DWORD
means 8 bytes.
Under x64 Linux, function arguments are passed via registers:
rdi: First Argument
rsi: Second Argument
rdx: Third Argument
rcx: Fourth Argument
r8: Fifth Argument
r9: Sixth Argument
The return value is store in rax
(eax
on 32-bit machines).
Register dereferencing occurs when the value of the register is treated as an address to the actual data to be used, rather than the data itself. This means that addressed can be stored in registers and used later - this is useful when dealing with large data sizes.
For example,
mov rax, [rdx]
Will check the value inside rdx
and treat it as an address - it will go to the location where this address points and get its data from there. It will then move this data into rax
. If we hadn't used []
, it would have treated the address in rdx
simply as a value and moved it directly into rax
.